/**
 Brainfuck-Robots Bluetooth App
 Copyright (C) <2014>  <Simon Grafenhorst>

 This file is part of the Brainfuck-Robots Bluetooth App.

 The Brainfuck-Robots Bluetooth App is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 The Brainfuck-Robots Bluetooth App is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with the Brainfuck-Robots Bluetooth App.  If not, see <http://www.gnu.org/licenses/>.
 */
package de.brainfuckrobots.bluetooth;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CompoundButton;

public class ControllingView extends View {


    private int backgroundX = 0;
    private int backgroundY;
    private final int variance = 85;
    private int maxDrag = 100;

    private int padX;
    private int padY;
    private int activePointerId;
    private final Paint bmPaint;


    private Bitmap padbg, pad;
    private String tag = "ControllingView";

    public ControllingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        padbg = BitmapFactory.decodeResource(getResources(), R.drawable.padbg);
        pad = BitmapFactory.decodeResource(getResources(), R.drawable.pad);
        padbg.setDensity(200);
        pad.setDensity(200);
        activePointerId = MotionEvent.INVALID_POINTER_ID;
        bmPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bmPaint.setFilterBitmap(true);
        bmPaint.setDither(true);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int density = getResources().getDisplayMetrics().densityDpi;
        backgroundY = getHeight() - density;
        padbg = Bitmap.createScaledBitmap(padbg, density, density, true);
        pad = Bitmap.createScaledBitmap(pad, 4 / 3 * density, 4 / 3 * density, true);
        maxDrag = 4 / 3 * density / 4;
        padX = backgroundX;
        padY = backgroundY;
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.setDensity((int) (getResources().getDisplayMetrics().densityDpi));
        canvas.drawBitmap(padbg, backgroundX, backgroundY, bmPaint);
        canvas.drawBitmap(pad, padX, padY, bmPaint);
        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int padPosX = padX + pad.getWidth() / 2;
        int padPosY = padY + pad.getHeight() / 2;
        final int action = event.getActionMasked();

        switch (action) {
            case MotionEvent.ACTION_DOWN: {
                if (event.getX() + variance > padPosX && event.getX() - variance < padPosX && event.getY() + variance > padPosY && event.getY() - variance < padPosY) {
                    final int pointerIndex = event.getActionIndex();

                    // Save the ID of this pointer (for dragging)
                    activePointerId = event.getPointerId(pointerIndex);
                }
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                if (activePointerId != MotionEvent.INVALID_POINTER_ID) {

                    // Find the index of the active pointer and fetch its position
                    final int pointerIndex = event.findPointerIndex(activePointerId);
                    final float x = event.getX(pointerIndex);
                    final float y = event.getY(pointerIndex);

                    if (!((CompoundButton) (MainActivity.getContext().findViewById(R.id.switch1))).isChecked())
                        setPad((int) x - pad.getWidth() / 2, (int) y - pad.getHeight() / 2);

                }
                break;
            }

            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP: {
                if (event.getPointerId(event.getActionIndex()) == activePointerId) {
                    resetPad();
                    activePointerId = MotionEvent.INVALID_POINTER_ID;
                }
                break;
            }
        }

        return true;
    }

    public void resetPad() {
        setPad(backgroundX, backgroundY);
    }

    public int getSpeed() {
        return (int) (Math.sqrt(Math.pow(padX - backgroundX, 2) + Math.pow(padY - backgroundY, 2)) / maxDrag * 127);
    }

    public int getAngle() {
        if (padX - backgroundX != 0) {
            return padX - backgroundX < 0 ? (int) (Math.toDegrees(Math.atan((double) (padY - backgroundY) / (double) (padX - backgroundX))) + 270) : (int) (Math.toDegrees(Math.atan((double) (padY - backgroundY) / (double) (padX - backgroundX))) + 90);
        } else {
            return padY - backgroundY <= 0 ? 0 : 180;
        }
    }

    private void correctPad() {
        if (Math.sqrt(Math.pow(padX - backgroundX, 2) + Math.pow(padY - backgroundY, 2)) > maxDrag) {
            int tempPadX = backgroundX + (int) ((padX - backgroundX) * Math.sqrt(Math.pow(maxDrag, 2) / (Math.pow(padX - backgroundX, 2) + Math.pow(padY - backgroundY, 2))));
            padY = backgroundY + (int) ((padY - backgroundY) * Math.sqrt(Math.pow(maxDrag, 2) / (Math.pow(padX - backgroundX, 2) + Math.pow(padY - backgroundY, 2))));
            padX = tempPadX;
        }
    }

    public void setPad(int X, int Y) {
        this.padX = X;
        this.padY = Y;
        correctPad();
        invalidate();
    }

    public void setRotationPad(int X, int Y) {
        setPad(backgroundX + X, backgroundY + Y);
    }

}
